package com.project.frba.bifront.client.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.user.client.rpc.IsSerializable;

public class DataTree implements IsSerializable{
	
	private Map<String, DataNode> nodes = new HashMap<String, DataNode>();
	private String[] properties;
	
	
	public DataTree(){	
	}
	
	
	public DataTree(String[] columnProperties, Cube cube){
		this.properties = columnProperties;
		this.buildTree(cube);
	}
	
	public String[] getProperties(){
		return this.properties;
	}
	
	private void buildTree(Cube cube){
		for (CubeDataRow row : cube.getRows()) {
			DataNode parentNode = null;
			for (int i = 0; i < properties.length; i++) {
				String propertyName = properties[i];
				String value = row.getValue(propertyName);
				if (i == 0) {
					parentNode = this.addValue(value, propertyName);
				} else {
					parentNode = this.addValue(value, parentNode, propertyName);		
				}
			}
		}
	}
	
	private DataNode addValue(String value, String propertyName){
		if (!nodes.containsKey(value)) {
			DataNode newNode = new DataNode();
			newNode.setNodeValue(value);
			newNode.setLevel(0);
			newNode.setPropertyName(propertyName);
			nodes.put(value, newNode);
		}
		return nodes.get(value);
	}
	
	private DataNode addValue(String value, DataNode parentNode, String propertyName){
		return parentNode.addChildNode(value, propertyName);
	}
	
	public List<DataNode> getNodesForLevel(Integer level){
		List<DataNode> levelNodes = new ArrayList<DataNode>();
		for (String value : nodes.keySet()) {
			levelNodes.addAll(nodes.get(value).getNodesForLevel(level));
		}
		
		return levelNodes;
	}
	
	public List<DataNode> getNodesByDepth(String initialValue){
		List<DataNode> depthNodes = new ArrayList<DataNode>();
		DataNode node = nodes.get(initialValue);
		node.setIndexRow(0);
		node.setIndexCol(0);
		depthNodes.add(node);
		depthNodes.addAll(node.getAllNodes());
		
		return depthNodes;
	}

	public Integer getIndexOfRow(CubeDataRow rowVO) {
		if(properties.length == 0){
			return -1;
		}
		List<String> valuesList = new ArrayList<String>();
		for (int i = 0; i < properties.length; i++) {
			valuesList.add(rowVO.getValue(properties[i]));
		}
		return this.getNodeByValues(valuesList).getRealIndex();
	}
	
	public DataNode getNodeByValues(List<String> valuesList){
		DataNode firstNode = this.nodes.get(valuesList.get(0));
		return firstNode.getNodeByValues(valuesList);
		
	}
	
	public String getLeafPropertyName(){
		return properties[properties.length - 1];
	}
	

}
